package com.yuanfeng.commoms.rocketmq.producer;

import com.yuanfeng.commoms.rocketmq.config.JmsConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author hyq
 * 消息 生产者
 */
@Component
@Slf4j
@RefreshScope
public class MqProducer {

    @Value("${rocketmq.name-server}")
    public String nameServer;

    protected String getProducerGroup() {
        return JmsConfig.PRODUCER_GROUP;
    }

    private DefaultMQProducer producer;

    public DefaultMQProducer getProducer(){
        return this.producer;
    }

    /**
     * 对象在使用之前必须要调用一次，只能初始化一次
     */
    @PostConstruct
    public void start(){
        producer = new DefaultMQProducer(getProducerGroup());
        producer.setNamesrvAddr(nameServer);

        try {
            this.producer.start();
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }


    /**
     * 一般在应用上下文，使用上下文监听器，进行关闭
     */
    @PreDestroy
    public void shutdown(){
        this.producer.shutdown();
    }


    /**
     * 同步 发送消息
     *
     * @param message 消息
     * @return 发送结果
     */
    public SendResult sendMsg(Message message) {
        try {
            SendResult sendResult = getProducer().send(message,10000);
            log.info("MQ消息发送成功!");
            return sendResult;
        } catch (Exception e) {
            throw new RuntimeException("MQ消息发送失败!", e);
        }
    }

    /**
     * 异步 发送消息
     *
     * @param message 消息
     */
    public void sendAsyMsg(Message message) {

        try {
            getProducer().send(message, new SendCallback() {
                @Override
                public void onSuccess(SendResult sendResult) {
                    log.info("MQ消息发送成功!");
                }

                @Override
                public void onException(Throwable throwable) {
                    //TODO 补偿操作，根据具体业务定制
                    throw new RuntimeException("MQ消息发送失败!", throwable);
                }
            });
        } catch (Exception e) {
            throw new RuntimeException("MQ消息发送失败!", e);
        }
    }


    /**
     * 延迟 发送消息
     *
     * @param message 消息
     * @param delayTimeLevel 延迟级别
     * @return 发送结果
     */
    public SendResult sendDelayMsg(Message message, int delayTimeLevel) {
        try {
            //xxx是级别，1表示配置里面的第一个级别，2表示第二个级别，延迟消费级别
            //"1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"
            message.setDelayTimeLevel(delayTimeLevel);

            SendResult sendResult = getProducer().send(message);
            log.info("MQ消息发送成功!");
            return sendResult;
        } catch (Exception e) {
            throw new RuntimeException("MQ消息发送失败!", e);
        }
    }

    /**
     * 延迟 发送消息
     *
     * @param message 消息
     * @return 发送结果
     */
    public SendResult sendDelayMsg(Message message) {
        return sendDelayMsg(message, 3);
    }

}
